package com.zh.chat.gui;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import com.zh.chat.controller.ClientContext;
import com.zh.chat.entity.UserStatus;
import com.zh.chat.util.ConfigUtil;

/**
 * 登陆界面 窗口工具不适用awt,使用swing
 * 
 * @author Administrator
 * 
 */
@SuppressWarnings("serial")
public class LoginFrame extends JFrame {
	/**
	 * 构造方法
	 */
	public LoginFrame() {
		init();
		initDeploy();
	}
	
	private TrayManager trayManager = new TrayManager();
	/**
	 * 界面初始化方法
	 */
	private void init() {
		// 设置窗口标题
		this.setTitle("SimCall");
		{//设置做左上角的图标
			URL url = this.getClass().getClassLoader().getResource("com/zh/chat/image/icon/32px.png");
			this.setIconImage(Toolkit.getDefaultToolkit().createImage(url));
		}
		// 设置窗口大小
		this.setSize(350, 240);
		this.setResizable(false);
		// 设置窗口居中
		this.setLocationRelativeTo(null);
		// 向窗口中添加组件
		this.panel = createContentPane();
		this.setContentPane(this.panel);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		/**
		 * WindowAdapter叫做适配器模式：
		 * 当我们需要定义一个类（无论是不是使用匿名类方式）去实现某个接口时，我们的需要时支队此接口中定义的某几个抽象方法感兴趣
		 * 但是因为接口的特点，我们的类必须要将所有的方法都实现，无论我们是不是需要去书写这些方法的方法逻辑，但是这样做在我们的类
		 * 中就会有很多空方法(方法中没有逻辑)，为了避免这样的情况发生。我们通常会使用适配器模式
		 * 
		 * 适配器模式中，会有一个类实现了接口的所有方法，我们称这个叫做适配器，当我们在定义类的时候，就不需要直接实现该接口，而是
		 * 去继承适配器类，这样我们只需要重写部分方法就可以，无需重写所有方法。
		 */
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				boolean flag = clientContext.exit(LoginFrame.this);
				if(flag){
					trayManager.removeTray();
					clientContext.stop();
					System.exit(0);
				}
			}
			@Override
			public void windowIconified(WindowEvent event) {
				LoginFrame.this.setVisible(false);
				trayManager.initLoginFrameTray(LoginFrame.this);
			}
			
			@Override
			public void windowOpened(WindowEvent e) {
				super.windowOpened(e);
				String serverIp = config.getString("SERVER_IP");
				int serverPort = config.getInt("SERVER_PORT");
				setServerIp(serverIp);//将配置文件中的ServerIP填入界面
				setServerPort(serverPort);//将配置文件中的ServerPort填入界面
			}
		});
	}

	// 创建主Panel
	private JPanel createContentPane() {
		JPanel panel = new JPanel(null);
		initIdPwd();
		initBtn();
		// logo label初始化
		JLabel logo = new JLabel("", JLabel.CENTER);
		logo.setBounds(0, 0, 350, 75);
		URL logoImg = this.getClass().getClassLoader()
				.getResource("com/zh/chat/image/titlelogo.png");
		logo.setIcon(new ImageIcon(logoImg));
		panel.add(logo);
		// 配置按钮初始化
		optionBtn.setBackground(new Color(240, 240, 240));
		optionBtn.setBounds(310, 180, 25, 25);
		optionBtn.setBorder(null);
		panel.add(optionBtn);
		// 错误消息label初始化
		JPanel msgPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
		msgPanel.setBounds(100, 150, 200, 23);
		this.message = new JLabel();
		msgPanel.add(message);
		statusBtn = new LoginStatusBtn();
		statusBtn.setBounds(30, 180, 55, 23);
		statusBtn.setClientContext(clientContext);
		statusBtn.setStatus(UserStatus.ONLINE);
		panel.add(statusBtn);
		panel.add(msgPanel);

		this.idlb.setBounds(30, 85, 80, 30);
		this.idField.setBounds(100, 85, 200, 30);
		this.pwdlb.setBounds(30, 120, 80, 30);
		this.pwdField.setBounds(100, 120, 200, 30);
		// 用户名密码框配置
		panel.add(idlb);
		panel.add(idField);
		panel.add(pwdlb);
		panel.add(pwdField);
		// 按钮
		loginBtn.setBounds(100, 175, 90, 30);
		registBtn.setBounds(210, 175, 90, 30);
		panel.add(loginBtn);
		panel.add(registBtn);
		return panel;
	}

	private void initIdPwd() {
		this.idlb = new JLabel("SC账号");
		this.idlb.setFont(new Font("宋体", Font.PLAIN, 15));
		this.idField = new JTextField();
		this.idField.setFont(new Font("宋体", Font.PLAIN, 15));
		this.pwdlb = new JLabel("密  码");
		this.pwdlb.setFont(new Font("宋体", Font.PLAIN, 15));
		this.pwdField = new JPasswordField();
		// 允许密码框输入法，应对linux的输入问题
		this.pwdField.enableInputMethods(true);
		this.pwdField.setEchoChar('○');
		this.pwdField.setFont(new Font("宋体", Font.PLAIN, 15));

	}

	private void initDeploy() {
		this.iplb = new JLabel("服务器IP");
		this.iplb.setFont(new Font("宋体", Font.PLAIN, 15));
		this.ipField = new JTextField();
		this.ipField.setFont(new Font("宋体", Font.PLAIN, 15));
		this.portlb = new JLabel("端口");
		this.portlb.setFont(new Font("宋体", Font.PLAIN, 15));
		this.portField = new JTextField();
		this.portField.setFont(new Font("宋体", Font.PLAIN, 15));
		this.iplb.setBounds(20, 220, 80, 30);
		this.ipField.setBounds(90, 220, 130, 30);
		this.portlb.setBounds(230, 220, 50, 30);
		this.portField.setBounds(270, 220, 50, 30);
		this.panel.add(iplb);
		this.panel.add(ipField);
		this.panel.add(portlb);
		this.panel.add(portField);
	}

	private void extendFrame() {
		this.setSize(350, 290);
		validate();
	}

	private void contractionFrame() {
		this.setSize(350, 240);
		validate();
	}

	/**
	 * 初始化按钮
	 * 
	 * @return
	 */
	private void initBtn() {
		// 注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		this.loginBtn = new JButton("登陆");
		this.loginBtn.setFont(new Font("宋体", Font.PLAIN, 15));
		this.registBtn = new JButton("注册");
		this.registBtn.setFont(new Font("宋体", Font.PLAIN, 15));
		this.optionBtn = new JButton();
		URL optImg = this.getClass().getClassLoader()
				.getResource("com/zh/chat/image/option.png");
		optionBtn.setIcon(new ImageIcon(optImg));
		// 增加动作监听器，监听其中的方法actionPerformed()
		// 在按钮点击完成时候执行！
		loginBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try{
					config.setPropertie("SERVER_PORT", getServerPort() + "");
					config.setPropertie("SERVER_IP", getServerIp());
					clientContext.login(getUserId(), getUserPwd(), getServerIp(), getServerPort(), getStatus());
					config.save();
				}catch(RuntimeException error){
					showError(error.getMessage());
				}
			}
		});
		registBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				clientContext.showRegistFrame();
			}
		});
		optionBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				if (extendable) {
					extendFrame();
					extendable = false;
				} else {
					contractionFrame();
					extendable = true;
				}
			}
		});
	}

	private ConfigUtil config = null;

	public void setConfig(ConfigUtil config) {
		this.config = config;
	}

	private ClientContext clientContext;

	// 设置ui界面的控制器
	public void setClientContext(ClientContext clientContext) {
		this.clientContext = clientContext;
		trayManager.setClientContext(clientContext);
	}

	private boolean extendable = true;
	private JLabel logo;
	private JLabel idlb, pwdlb, iplb, portlb;
	private JTextField idField;// 应该引用到ID输入控件
	private JPasswordField pwdField;
	private JTextField ipField, portField;
	private LoginStatusBtn statusBtn=null;
	private JLabel message;
	private JButton loginBtn, registBtn, optionBtn;
	private JPanel panel;

	public void setLogoImage(ImageIcon image) {
		this.logo.setIcon(image);
	}

	/**
	 * 通过该方法可以获取用户输入的ID
	 * 
	 * @return
	 */
	public Long getUserId() {
		if(idField.getText().equals("")){
			throw new RuntimeException("用户名不能为空");
		}
		Long id = null;
		try{
			id = new Long(idField.getText());
		}catch(NumberFormatException e){
			throw new RuntimeException("请输入正确的ID");
		}
		// 要避免空指针异常需要 this.idField = idField;
		return id;
	}

	/**
	 * 通过此方法可以获取窗口中用户输入的密码
	 * 
	 * @return
	 */
	public String getUserPwd() {
		if(new String(pwdField.getPassword()).equals("")){
			throw new RuntimeException("密码不能为空");
		}
		/**
		 * 注意要获取密码框中的内容不要调用getText()方法，官方不推荐使用，想获取密码框
		 * 内容调用getPassword()方法返回一个char[]
		 */
		return new String(pwdField.getPassword());// 将char[]转换为一个字符串并返回
	}
	/**
	 * 获取登陆窗口上的登陆状态
	 * @return
	 */
	public int getStatus() {
		return statusBtn.getStatus();
	}
	/**
	 * 获取登陆界面上填入的IP地址
	 * 
	 * @return
	 */
	public String getServerIp() {
		if(new String(ipField.getText()).equals("")){
			throw new RuntimeException("IP不能为空");
		}
		Pattern pattern = Pattern.compile("^([0-9]{1,3}\\.{1}){3}[0-9]{1,3}$");
		Matcher matcher = pattern.matcher(ipField.getText());
		if (matcher.matches()) {
			return ipField.getText();
		}else{
			throw new RuntimeException("IP地址格式不正确");
		}
	}

	/**
	 * 设置登陆界面IP地址
	 * 
	 * @param ipField
	 */
	public void setServerIp(String ip) {
		Pattern pattern = Pattern.compile("^([0-9]{1,3}\\.{1}){3}[0-9]{1,3}$");
		Matcher matcher = pattern.matcher(ip);
		if (matcher.matches()) {
			this.ipField.setText(ip);
		} else {
			showError("服务器IP地址格式错误");
		}
	}

	/**
	 * 获取界面上填入的端口号
	 * 
	 * @return
	 */
	public int getServerPort() {
		if(new String(portField.getText()).equals("")){
			throw new RuntimeException("PORT不能为空");
		}
		int port = -1;
		try{
			port = Integer.parseInt(portField.getText());
		}catch(NumberFormatException e){
			throw new RuntimeException("端口格式错误");
		}
		return port;
	}

	/**
	 * 设置登陆界面端口号
	 * 
	 * @param portField
	 */
	public void setServerPort(int port) {
		if (port > 65535 || port < 0) {
			showError("端口设置不正确");
		} else {
			this.portField.setText(port + "");
		}
	}

	public void showError(String message) {
		this.message.setText(message);
		this.message.setFont(new Font("宋体", Font.PLAIN, 15));
		this.message.setForeground(Color.red);
		/**
		 * 窗口抖动
		 */
		final Timer t = new Timer();
		// 获取当前窗口的坐标，用一个Point实例保存，其中有x和y
		final Point start = getLocation();
		t.schedule(new TimerTask() {
			int[] xOffset = { 0, 1, 2, 1, 0, -1, -2, -1, };
			int[] yOffset = { 0, -1, 2, 2, -1, -2, -2, 1, };
			int i = 0;

			public void run() {
				Point p = getLocation();
				p.x += xOffset[i++ % xOffset.length];
				p.y += yOffset[i++ % xOffset.length];
				setLocation(p);
			}
		}, 0, 20);
		// 给timer添加一个任务，用于在若干秒后停止Timer，停止晃动效果
		t.schedule(new TimerTask() {
			public void run() {
				setLocation(start);// 停止前还原窗口坐标
				t.cancel();
			}
		}, 300);
	}
}
